package com.accounting.client.frontend.product;

import java.util.List;
import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.common.MoneyField;
import com.accounting.client.frontend.packages.PackageRow;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.Currency;
import com.accounting.client.remote.enumeration.PackageType;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.PackageInfo;
import com.accounting.client.remote.obj.PackageItem;
import com.accounting.client.remote.obj.PurchaseRecord;
import com.accounting.client.remote.obj.User;
import com.accounting.client.remote.transfer.AddPackageRequest;
import com.accounting.client.remote.transfer.UpdatePurchaseRecordRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.SessionManager;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import corelib.client.CollectionUtil;
import corelib.client.Util;
import corelib.client.delegate.Action;
import corelib.client.delegate.CompleteCallback;
import corelib.client.delegate.Func1;
import corelib.client.linq.Linq;
import corelib.client.resource.CommonResources;
import corelib.client.ui.LazyWidget;
import corelib.client.ui.SimpleMask;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.Size;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.button.Button;
import corelib.client.ui.widget.form.DateBox;
import corelib.client.ui.widget.form.ImageWidget;
import corelib.client.ui.widget.form.IntInputBox;
import corelib.client.ui.widget.form.LabelWidget;
import corelib.client.ui.widget.form.SelectField;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.form.fomatters.ValueFormatter;
import corelib.client.ui.widget.layout.LabelAlignment;
import corelib.client.ui.widget.layout.RelativeColumn;
import corelib.client.ui.widget.layout.RelativeLayout;
import corelib.client.ui.widget.layout.RelativeRow;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;

public class UpdatePurchaseRecordPanel extends LazyWidget<FlowPanel> {
	
	private MoneyField  			 costField;
	private MoneyField  			 postageField;
	private IntInputBox 			 countField;
	private SelectField<User> 		 operatorField;
	private SelectField<User> 		 postOperatorField;
	private ImageWidget 		     addPackageIcon;
	private DateBox 			     datePurchasedField;
	private SelectField<StockLocation> locationField;
	private PurchaseRecord 			 record;
	private RelativeColumn 			 packageColumn;
	private RelativeColumn 			 buttonGroups;
	
	private Action action;
	private final List<PackageRow> packages = CollectionUtil.newArrayList();
	
	public UpdatePurchaseRecordPanel(PurchaseRecord item, Action action){
		this.record = item;
		this.action = action;
		this.packageColumn = new RelativeColumn();
		this.buttonGroups  = new RelativeColumn();
	}
	
	@Override
	protected FlowPanel createWidget() {
		FlowPanel panel = new FlowPanel();
		panel.getElement().getStyle().setPadding(10, Unit.PX);
		
		RelativeColumn column = new RelativeColumn();
		int lw = 100;
		int fw = 100;
		
		operatorField = new SelectField<User>(ApplicationContext.getAllUsers());
		operatorField.setNullable(true);
		operatorField.setOptionFormatter("请选择操作员", new ValueFormatter<User>(){
			@Override
			public String format(User value) {
				return value.getCName();
			}
		});
		
		postOperatorField = new SelectField<User>(ApplicationContext.getAllUsers());
		postOperatorField.setNullable(true);
		postOperatorField.setOptionFormatter("请选择操作员", new ValueFormatter<User>(){
			@Override
			public String format(User value) {
				return value.getCName();
			}
		});
		
		addPackageIcon = new ImageWidget(BoxResources.INSTANCE.plus16(), new Size(16, 16), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				PackageRow row = new PackageRow(packages);
				packages.add(row);
				packageColumn.addRow(row);
			}
		});
		
		datePurchasedField = new DateBox();
		countField = new IntInputBox();
		costField  = new MoneyField(Currency.AUD);
		costField.setValueEnable(true);
		postageField = new MoneyField(Currency.AUD);
		postageField.setEnable(false);
		locationField = createLocationField();
		locationField.setNullable(true);
		locationField.setOptionFormatter("请选择库存位置", new ValueFormatter<StockLocation>(){
			@Override
			public String format(StockLocation value) {
				return value.getCname();
			}
		});
		
		addPackageIcon.setEnabled(false);
		postageField.setValueEnable(false);
		postageField.getValueField().setDouble(0.0, false);
		
		column.addRow().add(new LabelWidget("*更新购买记录时请注意单件购买成本，购买员，邮寄员，邮费，汇率的匹配").setColor("red").setBold(true), 600);
		column.addRow();
		
		RelativeRow row = column.addRow();
		row.add(new SimpleLabel(Util.EMPTY_STRING).setBold(true), new SimpleLabel(record.getProductName()).setBold(true), RelativeLayout.create(200, LabelAlignment.Top, lw));
		row.add(new SimpleLabel("数量").setBold(true), countField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("单件成本").setBold(true), costField.getValueField(), RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("购买员").setBold(true), operatorField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("邮寄员").setBold(true), postOperatorField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("单件邮费").setBold(true), postageField.getValueField(), RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("库存位置").setBold(true), locationField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("购买日期").setBold(true), datePurchasedField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel(Util.EMPTY_STRING), addPackageIcon, RelativeLayout.create(24, LabelAlignment.Top, 24));
		
		Button submitBtn = new Button("递交更新", CommonResources.INSTANCE.accept16(), new WidgetListener() {
			@Override
			public void valueUpdated(Widget widget) {
				updatePurchaseRecord();
			}
		});
		
		Button resetBtn = new Button("重置", CommonResources.INSTANCE.accept16(), new WidgetListener() {
			@Override
			public void valueUpdated(Widget widget) {
				packages.clear();
				packageColumn.clear();
				reset();
			}
		});
		
		buttonGroups.addRow().addSpace(200).add(submitBtn, 100).addSpace(12).add(resetBtn, 100);
		packageColumn.setRowSpacing(10);
		
		column.setRowSpacing(12);
		column.addRow().add(packageColumn);
		column.addRow().add(buttonGroups);
		panel.add(column.getPanel());
		return panel;
	}

	private SelectField<StockLocation> createLocationField() {
		return new SelectField<StockLocation>(StockLocation.All, new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				if (locationField.getSelectedOption().getLocation() == StockLocation.China.getLocation()){
					postageField.setEnable(true);
					addPackageIcon.setEnabled(true);
					return;
				}
				
				postageField.setEnable(false);
				addPackageIcon.setEnabled(false);
				postageField.getValueField().setDouble(0.0);
				packageColumn.clear();
				packages.clear();
			}
		});
	}
	
	@Override
	protected void afterCreateWidget(FlowPanel widgetCreated) {
		super.afterCreateWidget(widgetCreated);
		reset();
	}
	
	private void reset() {
		if (this.record != null) {
			loadPackages(this.record);
			this.datePurchasedField.setDate(this.record.getDateCreated());
			this.locationField.setSelectedOption(StockLocation.getLocationByType(this.record.getLocation()), true);
			this.countField.setInteger(this.record.getCount(), false);
			this.costField.getValueField().setDouble(this.record.getCost(), false);
			this.postageField.getValueField().setDouble(this.record.getPostage(), false);
			this.operatorField.setSelectedOption(ApplicationContext.getUser(this.record.getOperatorId()));
			this.postOperatorField.setSelectedOption(ApplicationContext.getUser(this.record.getPostOperatorId()));
		}
	}
	
	private void loadPackages(PurchaseRecord record){
		String passport = SessionManager.getPassport();
		SimpleMask.mask(this, "加载包裹...");
		Services.PackageService.ListPackagesByReference(passport, record.getId(),
			new AsyncCallback<List<PackageInfo>>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleMask.unmask(UpdatePurchaseRecordPanel.this);
					ErrorHandler.handleServiceError(caught);
				}
				@Override
				public void onSuccess(List<PackageInfo> result) {
					SimpleMask.unmask(UpdatePurchaseRecordPanel.this);
					for (PackageInfo info : result) {
						 PackageRow row = new PackageRow(packages);
						 row.setItem(info);
						 packageColumn.addRow(row);
						 packages.add(row);
					}
				}
			}
		);
	}
	
	private List<PackageItem> getPackageItems(){
		return Linq.select(packages, new Func1<PackageRow, PackageItem>(){
			   @Override
			   public PackageItem run(PackageRow param) {
				  return param.getItem();
			   }
		});
	}
	
	private void updatePurchaseRecord() {
		if (countField.getInteger(0) <= 0){
			countField.markError("请输入购买产品数量 (产品数量不能为零)");
			return;
		}
		
		if (costField.getValue() == 0.0){
			costField.getValueField().markError("请输入产品成本 (产品购买单价不能为零).");
			return;
		}
		
		if (operatorField.getSelectedOption() == null){
			operatorField.markError("请选择购买员.");
			return;
		}
		
		if (postOperatorField.getSelectedOption() == null){
			postOperatorField.markError("请选择邮寄员.");
			return;
		}
		
		if (locationField.getSelectedOption() == null) {
			locationField.markError("请选择产品存放位置.");
			return;
		}
		
		if (locationField.getSelectedOption() == StockLocation.China) {
			if (postageField.getValue() == 0.0) {
				postageField.getValueField().markError("发往中国的产品邮费不能为零");
				return;
			}
			if (packages == null || CollectionUtil.isEmpty(packages)) {
				SimpleMessageBox.error("错误", "发往中国的库存必须输入物流信息，请点击绿色加号增加物流包裹信息", CompleteCallback.Nil);
				return;
			}
			else {
				for (PackageRow row : packages) {
					 if (row.validate() == Boolean.FALSE){
						 return;
					 }
				}
			}
		}
		
		SimpleModal.show("更新购买记录。。。");
		UpdatePurchaseRecordRequest request = new UpdatePurchaseRecordRequest();
		request.setId(record.getId());
		request.setOperatorId(operatorField.getSelectedOption().getUserId());
		request.setPostOperatorId(postOperatorField.getSelectedOption().getUserId());
		request.setLocation(locationField.getSelectedOption().getLocation());
		request.setCost (costField.getValue());
		request.setCount(countField.getInteger());
		request.setDatePurchased(datePurchasedField.getDate());
		
		String passport = SessionManager.getPassport();
		Services.ProductService.UpdatePurchaseRecord(passport, request,
			new AsyncCallback<Boolean>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(Boolean result) {
					SimpleModal.hide();
					if (locationField.getSelectedOption() == null 
					 || locationField.getSelectedOption() == StockLocation.Sydney){
						return;
					}
					
					Services.PackageService.RemovePackages(SessionManager.getPassport(), record.getId(), new AsyncCallback<Boolean>(){
						@Override
						public void onFailure(Throwable caught) {
							ErrorHandler.handleServiceError(caught);
						}
						
						@Override
						public void onSuccess(Boolean result) {
							if (result == Boolean.TRUE){
								addPackages();
							}
						}
					});
				}
			}
		);
	}
	
	private void addPackages() {
		List<PackageItem> packages = getPackageItems();
		for (PackageItem packageItem : packages) {
			 packageItem.setReference(record.getId());
			 packageItem.setShippingAddress(locationField.getSelectedOption().getCname());
			 packageItem.setType(PackageType.Stock.getType());
			 packageItem.setDescription(record.getProductName());
			 packageItem.setDateCreated(record.getDateCreated());
		}
		
		AddPackageRequest request = new AddPackageRequest();
		request.setPackageItems(packages);
		SimpleModal.show("创建物流包裹...");
		Services.PackageService.AddPackage(SessionManager.getPassport(), request, new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
				ErrorHandler.handleServiceError(caught);
			}
			
			@Override
			public void onSuccess(Boolean result) {
				SimpleModal.hide();
				if (action != null){
					action.run();
				}
			}
		});
	}
	
}
